package cn.cdeden.knowledge.service.impl;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.core.utils.StringUtils;
import cn.cdeden.common.core.utils.page.TableDataInfo;
import cn.cdeden.common.mybatis.validator.QueryHelpMybatisPlus;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.SysDocLog;
import cn.cdeden.knowledge.domain.SysLogPerm;
import cn.cdeden.knowledge.domain.dto.SysDocLogDto;
import cn.cdeden.knowledge.enums.TreeEnum;
import cn.cdeden.knowledge.mapper.SysDocLogMapper;
import cn.cdeden.knowledge.service.SysDocLogService;
import cn.cdeden.knowledge.service.SysLogPermService;
import cn.cdeden.knowledge.utils.PageUtil;
import cn.cdeden.knowledge.domain.dto.SysLogPermQueryParam;
import cn.cdeden.system.api.RemoteDeptService;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.domain.vo.RemoteDeptVo;
import cn.cdeden.system.api.model.LoginUser;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import cn.cdeden.knowledge.domain.dto.SysDocLogQueryParam;
import lombok.AllArgsConstructor;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
* @author GW
* @date 2024-01-19
*/
@Service
@AllArgsConstructor
// @CacheConfig(cacheNames = SysEnterpriseLogService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class SysDocLogServiceImpl extends ServiceImpl<SysDocLogMapper, SysDocLog> implements SysDocLogService {

    // private final RedisUtils redisUtils;
    private final SysDocLogMapper sysDocLogMapper;

    private final SysLogPermService sysLogPermService;
    @DubboReference(check = false)
    private final RemoteUserService sysUserService;
    @DubboReference(check = false)
    private final RemoteDeptService sysDeptService;
    @Override
    public TableDataInfo<SysDocLogDto> queryAll(SysDocLogQueryParam query, Pageable pageable) {
        IPage<SysDocLog> queryPage = PageUtil.toMybatisPage(pageable);
        QueryWrapper<SysDocLog> predicate = QueryHelpMybatisPlus.getPredicate(query);
        String nickName = query.getNickName();
        String deptName = query.getDeptName();
        if (!StringUtils.isNullOrBlank(nickName)){
            List<LoginUser> sysUserDtos = sysUserService.selectUserByNickName(nickName);
            if (sysUserDtos.size() > 0) {
                List<Long> collect = sysUserDtos.stream().map(LoginUser::getUserId).collect(Collectors.toList());
                predicate.lambda().in(SysDocLog::getOperatorId,collect);
            }
            else {
                return new TableDataInfo<>();
            }
        }
        if (!StringUtils.isNullOrBlank(deptName)){
            List<RemoteDeptVo> deptDtos = sysDeptService.selectUserByDeptName(deptName);
            if (deptDtos.size() > 0) {
                List<Long> collect = deptDtos.stream().map(RemoteDeptVo::getDeptId).collect(Collectors.toList());
                predicate.lambda().in(SysDocLog::getOperatorDept,collect);
            }else {
                return new TableDataInfo<>();
            }
        }
        IPage<SysDocLog> page = sysDocLogMapper.selectPage(queryPage,predicate);
        TableDataInfo<SysDocLog> build = TableDataInfo.build(page);
        TableDataInfo<SysDocLogDto> sysDocLogDtoTableDataInfo = MapstructUtils.convertTableDataInfo(build, SysDocLogDto.class);
//        PageInfo<SysDocLogDto> sysDocLogDtoPageInfo = ConvertUtil.convertPage(page, SysDocLogDto.class, pageable);
        List<SysDocLogDto> content = sysDocLogDtoTableDataInfo.getRows();
        for (SysDocLogDto sysDocLogDto : content) {
            SysLogPermQueryParam sysLogPermQueryParam = new SysLogPermQueryParam();
            sysLogPermQueryParam.setLogId(sysDocLogDto.getId());
            sysDocLogDto.setIsHasChildren(sysLogPermService.queryAll(sysLogPermQueryParam).size() > 0);
        }
        return sysDocLogDtoTableDataInfo;
    }

    @Override
    public List<SysDocLogDto> queryAll(SysDocLogQueryParam query){
        return MapstructUtils.convert(sysDocLogMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), SysDocLogDto.class);
    }

    @Override
    public SysDocLog getById(Long id) {
        return sysDocLogMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public SysDocLogDto findById(Long id) {
        return MapstructUtils.convert(getById(id), SysDocLogDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean insert(SysDocLogDto resources) {
        SysDocLog entity = MapstructUtils.convert(resources, SysDocLog.class);
        return this.save(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateById(SysDocLogDto resources){
        SysDocLog entity = MapstructUtils.convert(resources, SysDocLog.class);
        boolean ret = this.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteByIds(Set<Long> ids){
        if (ids == null||ids.size() == 0){
            baseMapper.delete(null);
            sysLogPermService.deleteByIds(null);
        }
        // delCaches(ids);
        return this.removeByIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id){
        Set<Long> set = new HashSet<>(1);
        set.add(id);
        return this.deleteByIds(set);
    }

    /*
    private void delCaches(Long id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<Long> ids) {
        for (Long id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<SysEnterpriseLogDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (SysEnterpriseLogDto sysEnterpriseLog : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("操作者", sysEnterpriseLog.getOperatorId());
              map.put("企业文档/团队文档", sysEnterpriseLog.getType());
              map.put("操作类型", sysEnterpriseLog.getOperationType());
              map.put("文档类型", sysEnterpriseLog.getDocumentName());
              map.put("文档路径", sysEnterpriseLog.getDocumentPath());
              map.put("文档状态", sysEnterpriseLog.getDocumentStatus());
              map.put("拥有者编号", sysEnterpriseLog.getCreateId());
              map.put("创建者", sysEnterpriseLog.getCreateBy());
              map.put("创建日期", sysEnterpriseLog.getCreateTime());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/

    /**
     * 创建日志信息
     * @param userDto 用户对象
     * @param type 文档类型
     * @param operationType 操作类型 如：新增文件夹、新增文件、变更权限等。
     * @param documentName 文档名称
     * @param documentPath 文档路径
     * @param documentStatus 文档状态 null=正常,1=删除至一级回收站,2=删除至二级级回收站,3=彻底删除
     */
    @Override
    public void createLog(String documentId, LoginUser userDto, TreeEnum type, String operationType, String documentName, String documentPath, String documentStatus){
        if (userDto==null){
            userDto = LoginHelper.getLoginUser();
        }
        SysDocLog sysDocLog = new SysDocLog(userDto.getUserId(),documentId,type.getType(),operationType,documentName,documentPath,documentStatus,userDto.getDeptId());
        sysDocLogMapper.insert(sysDocLog);
    }

    /**
     * 创建权限日志信息
     * @param userDto 用户对象
     * @param type 文档类型
     * @param operationType 操作类型 如：新增文件夹、新增文件、变更权限等。
     * @param documentName 文档名称
     * @param documentPath 文档路径
     * @param documentStatus 文档状态 null=正常,1=删除至一级回收站,2=删除至二级级回收站,3=彻底删除
     * @param sysLogPermDtos 权限集合
     */
    @Override
    public void createPermLog(String documentId,LoginUser userDto, TreeEnum type, String operationType, String documentName, String documentPath, String documentStatus, List<SysLogPerm> sysLogPermDtos){
        if (userDto==null){
            userDto = LoginHelper.getLoginUser();
        }
        //新增文档日志信息
        SysDocLog sysDocLog = new SysDocLog(userDto.getUserId(),documentId, type.getType(),operationType,documentName,documentPath,documentStatus, userDto.getDeptId());
        sysDocLogMapper.insert(sysDocLog);
        Long id = sysDocLog.getId();
        sysLogPermDtos.stream().forEach(action->{
            action.setLogId(id);
            action.setType(type.getType());
        });
        //新增权限日志信息
        sysLogPermService.insertBatch(sysLogPermDtos);
    }
}
